package com.meida.module.arc.provider.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.service.BaseAdminUserService;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.vo.JoinBean;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.module.arc.client.entity.ArcUse;
import com.meida.module.arc.client.entity.ArcUseRecord;
import com.meida.module.arc.client.entity.ArcUseRemind;
import com.meida.module.arc.client.enums.ArchiveEnumInteger;
import com.meida.module.arc.provider.mapper.ArcUseRecordMapper;
import com.meida.module.arc.provider.service.ArcUseRecordService;
import com.meida.module.arc.provider.service.ArcUseRemindService;
import com.meida.module.arc.provider.service.ArcUseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 档案借阅记录接口实现类
 *
 * @author flyme
 * @date 2022-01-06
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ArcUseRecordServiceImpl extends BaseServiceImpl<ArcUseRecordMapper, ArcUseRecord> implements ArcUseRecordService {

    @Autowired
    private ArcUseRemindService arcUseRemindService;

    @Autowired
    private ArcUseService arcUseService;

    @Autowired
    private BaseAdminUserService baseAdminUserService;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ArcUseRecord aur, EntityMap extra) {
        ApiAssert.isNotEmpty("姓名不能为空",aur);
        ApiAssert.isNotEmpty("借阅案不能为空",aur.getUseId());
        ApiAssert.isNotEmpty("全宗id不能为空",aur.getQzId());
        ApiAssert.isNotEmpty("借阅方式不能为空",aur.getUseType());
        ArcUse use = arcUseService.getById(aur.getUseId());
        aur.setUseUserId(OpenHelper.getUserId());
        aur.setUseUserName(OpenHelper.getUser().getNickName());
        ApiAssert.isNotEmpty("借阅案不能为空", use);
        if(ArchiveEnumInteger.IS_TRUE.getCode().equals(use.getIsRemove())){
            ApiAssert.failure("借阅档案已经移除待借，无法借阅");
        }
        if(2==aur.getUseType()
                &&ArchiveEnumInteger.IS_TRUE.getCode().equals(use.getIsUseSubstance())){
            ApiAssert.failure("借阅档案已经被实体借阅或已被申请，无法再次实体借阅");
        }

        if(2==aur.getUseType()){
            LambdaUpdateWrapper<ArcUse> lambdaUpdateWrapper = new LambdaUpdateWrapper<ArcUse>();
            lambdaUpdateWrapper.eq(ArcUse::getUseId,use.getUseId())
                    .set(ArcUse::getIsUseSubstance,ArchiveEnumInteger.IS_TRUE.getCode());
            this.arcUseService.update(lambdaUpdateWrapper);
        }


        aur.setBorrowDay(0);
        aur.setIsPrint(0);
        aur.setIsDownload(0);
        aur.setDownloadCount(0);
        aur.setVerifyType(1);

        return ResultBody.ok();
    }

    @Override
    public ResultBody afterAdd(CriteriaSave cs, ArcUseRecord record, EntityMap extra) {
        ArcUse use = arcUseService.getById(record.getUseId());

        this.arcUseRemindService.createRemid(1, "提交了档案借阅申请", FlymeUtils.isEmpty(use.getArchiveName()) ? use.getArcNo() : use.getArchiveName(), record.getQzId(), OpenHelper.getUserId(), null, null);
        return super.afterAdd(cs, record, extra);
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<ArcUseRecord> cd) {
        Long[] ids = cd.getIds();
        ApiAssert.isNotEmpty("删除对象不能为空", ids);
        List<ArcUseRecord> list = this.listByIds(Arrays.asList(ids));
        ApiAssert.isNotEmpty("删除对象不能为空", list);
        //1待审核2驳回3待归还4已归还5逾期归还
        list.forEach(item -> {
            if (2 != item.getVerifyType() && 4 != item.getVerifyType()) {
                ApiAssert.failure("只有已驳回和已归还的借阅记录可以删除");
            }
        });
        return ResultBody.ok();
    }



    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ArcUseRecord> cq, ArcUseRecord aur, EntityMap requestMap) {
        this.executeExpireTime();
        ApiAssert.isNotEmpty("全宗id不能为空",aur);
        ApiAssert.isNotEmpty("全宗id不能为空",aur.getQzId());
        String queryType = requestMap.get("queryType");

        ApiAssert.isNotEmpty("查询类型不能为空",queryType);

        JoinBean join = cq.createJoin(ArcUse.class);
        join.setJoinField("useId");
        join.setMainField("useId");
        cq.like(ArcUse.class,"categoryName",requestMap.get("categoryName"));
        cq.like(ArcUse.class,"arcNo",requestMap.get("arcNo"));
        cq.like(ArcUse.class,"archiveName",requestMap.get("archiveName"));
        Object arcInfoId = requestMap.get("arcInfoId");
        if(FlymeUtils.isNotEmpty(arcInfoId)){
            cq.eq(ArcUse.class,"arcInfoId",Long.parseLong(arcInfoId.toString()));
        }

        cq.eq(ArcUseRecord.class,"useType");
        cq.like(ArcUseRecord.class,"useTime");
        cq.like(ArcUseRecord.class,"returnTime");
        cq.eq(ArcUseRecord.class,"borrowDay");
        cq.eq(ArcUseRecord.class,"verifyType");
        cq.eq(ArcUseRecord.class,"useUnitId");
        cq.eq(ArcUseRecord.class,"useCardType");
        cq.like(ArcUseRecord.class,"useCardNum");
        cq.like(ArcUseRecord.class,"useUserName");
        cq.like(ArcUseRecord.class, "verifyUserName");
        cq.like(ArcUseRecord.class, "rejectRemark");
        cq.eq(ArcUseRecord.class,"qzId",aur.getQzId());

        Object noVerifyType = requestMap.get("noVerifyType");
        if(FlymeUtils.isNotEmpty(noVerifyType)){
            cq.ne("aur.verifyType",Integer.parseInt(noVerifyType.toString()));
        }

        if("1".equals(queryType)){
            cq.eq(ArcUseRecord.class,"useUserId",OpenHelper.getUserId());
        }
        cq.addSelect(ArcUse.class,"qzId","unitId","categoryId","categoryName","arcInfoId","arcNo"
                ,"archiveName","originalCount","isUseSubstance");
        cq.addSelect(ArcUseRecord.class,"useRecordId","useId","useUserName","useUnitId","useCardType"
                ,"useCardNum","usePhone","usePurpose","useType","useTime","returnTime","borrowDay"
                ,"isOriginal","isPrint","isDownload","downloadCount","canDownloadCount","verifyUserId","verifyUserName","verifyType","rejectRemark");
        cq.orderByDesc("aur.createTime");
        return ResultBody.ok();
    }

    private void executeExpireTime(){
        try{
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String now = sdf.format(new Date());
//            LambdaQueryWrapper<ArcUseRecord> queryWrapper = new LambdaQueryWrapper<>();
//            queryWrapper.eq(ArcUseRecord::getVerifyType,3)
//                    .lt(ArcUseRecord::getReturnTime,now);
//            List<ArcUseRecord> recods = this.list(queryWrapper);
//            if(FlymeUtils.isNotEmpty(recods)){
//                recods.forEach(item->{
//                    LambdaUpdateWrapper<ArcUse> lambdaUpdateWrapper = new LambdaUpdateWrapper<ArcUse>();
//                    lambdaUpdateWrapper.eq(ArcUse::getUseId,item.getUseId())
//                            .set(ArcUse::getIsUseSubstance,ArchiveEnumInteger.IS_FALSE.getCode());
//                    this.arcUseService.update(lambdaUpdateWrapper);
//                });
//            }

            LambdaUpdateWrapper<ArcUseRecord> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(ArcUseRecord::getVerifyType,3).eq(ArcUseRecord::getUseType,1)
                    .lt(ArcUseRecord::getReturnTime,now).set(ArcUseRecord::getVerifyType,4);

            LambdaUpdateWrapper<ArcUseRecord> updateWrapper1 = new LambdaUpdateWrapper<>();
            updateWrapper1.eq(ArcUseRecord::getVerifyType,3).eq(ArcUseRecord::getUseType,2)
                    .lt(ArcUseRecord::getReturnTime,now).set(ArcUseRecord::getVerifyType,5);

            this.update(updateWrapper1);
            this.update(updateWrapper);
        }catch (Exception e){
            log.error("执行变更借阅过期异常",e);
        }
    }

    @Override
    public ResultBody changeStatus(Map param) {
        Object changeType = param.get("changeType");
        ApiAssert.isNotEmpty("变更状态不能为空",changeType);
        switch (changeType.toString()){
            case "back":
                Object useRecordIds = param.get("useRecordId");
                ApiAssert.isNotEmpty("要归还的申请记录为空",useRecordIds);
                String[] useRecordIdArr = useRecordIds.toString().split(",");
                LambdaQueryWrapper<ArcUseRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.in(ArcUseRecord::getUseRecordId,Arrays.stream(useRecordIdArr).map(item->{
                    return Long.parseLong(item);
                }).collect(Collectors.toList()));
                List<ArcUseRecord> list = this.list(lambdaQueryWrapper);
                ApiAssert.isNotEmpty("要归还的申请记录为空",useRecordIds);
                //1待审核2驳回3待归还4已归还5逾期归还
                list.forEach(item->{
                    if(item.getVerifyType()!=3&&item.getVerifyType()!=5){
                        ApiAssert.failure("只有待归还和预期归还的档案可以归还");
                    }
                    if(2==item.getUseType()){
                        LambdaUpdateWrapper<ArcUse> lambdaUpdateWrapper = new LambdaUpdateWrapper<ArcUse>();
                        lambdaUpdateWrapper.eq(ArcUse::getUseId,item.getUseId())
                                .set(ArcUse::getIsUseSubstance,ArchiveEnumInteger.IS_FALSE.getCode());
                        this.arcUseService.update(lambdaUpdateWrapper);
                    }
                });
                ArcUseRecord record = new ArcUseRecord();
                record.setVerifyType(4);
                this.update(record,lambdaQueryWrapper);

                break;
        }

        return ResultBody.ok();
    }

    @Override
    public ResultBody verify(Map param) {
        Object useTime = param.get("useTime");
        Object returnTime = param.get("returnTime");
        Object borrowDay = param.get("borrowDay");
        Object verifyType = param.get("verifyType");
        Object useRecordId = param.get("useRecordId");
        ApiAssert.isNotEmpty("审核状态不能为空", verifyType);
        ArcUseRecord record = this.getById(Long.parseLong(useRecordId.toString()));
        ApiAssert.isNotEmpty("申请信息不能为空", record);
        String key = "useverify";
        String useverify = redisUtils.getString(key);
        if (StrUtil.isNotEmpty(useverify)) {

        }
        if (record.getUseType() != 1 && record.getUseType() != 2) {
            ApiAssert.failure("借阅类型只能是实体或电子借阅");
        }
        record.setVerifyUserId(OpenHelper.getUserId());
        record.setVerifyUserName(OpenHelper.getUser().getNickName());
        if ("2".equals(verifyType.toString())) {
            Object rejectRemark = param.get("rejectRemark");
            record.setVerifyType(Integer.parseInt(verifyType.toString()));
            record.setRejectRemark(rejectRemark == null ? null : rejectRemark.toString());
            this.updateById(record);

            if(2==record.getUseType()){
                LambdaUpdateWrapper<ArcUse> lambdaUpdateWrapper = new LambdaUpdateWrapper<ArcUse>();
                lambdaUpdateWrapper.eq(ArcUse::getUseId,record.getUseId())
                        .set(ArcUse::getIsUseSubstance,ArchiveEnumInteger.IS_FALSE.getCode());
                this.arcUseService.update(lambdaUpdateWrapper);
            }


            ArcUseRemind remind = new ArcUseRemind();
            ArcUse use = this.arcUseService.getById(record.getUseId());
            remind.setQzId(record.getQzId());
            remind.setTitle(String.format("您所借阅的【%s】%s申请已被驳回",FlymeUtils.isEmpty(use.getArchiveName())?use.getArcNo():use.getArchiveName(),record.getUseType()==2?"实体借阅":"电子借阅"));
            remind.setContent(String.format("原因:%s",record.getRejectRemark()));
            remind.setType(1);
            remind.setUserId(record.getUseUserId());
            remind.setIsRead(0);
            remind.setUseId(record.getUseId());
            remind.setUseRecordId(record.getUseRecordId());
            remind.setCreateTime(new Date());
            remind.setVerifyUserId(OpenHelper.getUserId());
            this.arcUseRemindService.save(remind);

        }else if("3".equals(verifyType.toString())){
            ApiAssert.isNotEmpty("出借时间不能为空",useTime);
            ApiAssert.isNotEmpty("归还时间不能为空",returnTime);
            ApiAssert.isNotEmpty("借阅天数不能为空",borrowDay);
            ApiAssert.isNotEmpty("申请信息不能为空",useRecordId);
            record.setVerifyType(3);
            record.setUseTime(useTime.toString());
            record.setReturnTime(returnTime.toString());
            record.setBorrowDay(Integer.parseInt(borrowDay.toString()));

            if(1==record.getUseType()){
                Object isOriginal = param.get("isOriginal");
                Object isPrint = param.get("isPrint");
                Object isDownload = param.get("isDownload");
                Object canDownloadCount = param.get("canDownloadCount");
                Object canPrintCount = param.get("canPrintCount");
                ApiAssert.isNotEmpty("原文预览不能为空",isOriginal);
                ApiAssert.isNotEmpty("原文打印不能为空",isPrint);
                ApiAssert.isNotEmpty("原文下载不能为空",isDownload);
                record.setIsOriginal(Integer.parseInt(isOriginal.toString()));
                record.setIsPrint(Integer.parseInt(isPrint.toString()));
                record.setIsDownload(Integer.parseInt(isDownload.toString()));
                if("1".equals(isDownload.toString())){
                    ApiAssert.isNotEmpty("下载次数不能为空",canDownloadCount);
                    record.setCanDownloadCount(Integer.parseInt(canDownloadCount.toString()));
                    record.setDownloadCount(0);
                }
                if("1".equals(isPrint.toString())){
                    ApiAssert.isNotEmpty("打印次数不能为空",canPrintCount);
                    record.setCanPrintCount(Integer.parseInt(canPrintCount.toString()));
                    record.setPrintCount(0);
                }
            }else{
                record.setIsOriginal(ArchiveEnumInteger.IS_FALSE.getCode());
                record.setIsPrint(ArchiveEnumInteger.IS_FALSE.getCode());
                record.setIsDownload(ArchiveEnumInteger.IS_FALSE.getCode());
            }


            ArcUseRemind remind = new ArcUseRemind();
            ArcUse use = this.arcUseService.getById(record.getUseId());
            remind.setQzId(record.getQzId());
            remind.setTitle(String.format("您所借阅的【%s】%s申请已通过审核",FlymeUtils.isEmpty(use.getArchiveName())?use.getArcNo():use.getArchiveName(),record.getUseType()==2?"实体借阅":"电子借阅"));
            remind.setContent(String.format("开通:%s%s%s%s天借阅时间."
                    , record.getIsOriginal() == 1 ? "原文浏览," : ""
                    , record.getIsPrint() == 1 ? "打印," : ""
                    , record.getIsDownload() == 1 ? "下载(" + record.getCanDownloadCount() + ")次," : ""
                    , record.getBorrowDay()));
            remind.setType(1);
            remind.setUserId(record.getUseUserId());
            remind.setIsRead(0);
            remind.setUseId(record.getUseId());
            remind.setUseRecordId(record.getUseRecordId());
            remind.setCreateTime(new Date());
            remind.setVerifyUserId(OpenHelper.getUserId());

            this.arcUseRemindService.save(remind);

            this.updateById(record);


        }else{
            return ResultBody.failed("审核状态只能是确认出借或驳回");
        }
        return ResultBody.ok();
    }

    @Override
    public ResultBody usePurposeStatistics(Map param) {
        Object qzId = param.get("qzId");
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        Object beginUseTime = param.get("beginUseTime");
        Object endUseTime = param.get("endUseTime");
        Map mapperParam = new HashMap<>();
        mapperParam.put("qzId",Long.parseLong(qzId.toString()));
        if(FlymeUtils.isNotEmpty(beginUseTime)){
            mapperParam.put("beginUseTime",beginUseTime.toString());
        }
        if(FlymeUtils.isNotEmpty(endUseTime)){
            mapperParam.put("endUseTime",endUseTime.toString());
        }
        List<Map> queryResult = this.baseMapper.usePurposeStatistics(mapperParam);
        //借阅目的1工作查考2学术研究3经济建设4落实政策5个人取证6其他
        //审核状态 1待审核2驳回3待归还4已归还5逾期归还


        return ResultBody.ok(queryResult);
    }

    @Override
    public ResultBody useStatistics(Map param) {
        //待借文件库   待审核文件  待归还文件  逾期催还文件 档案利用人  黑名单利用人
        Object qzId = param.get("qzId");
        ApiAssert.isNotEmpty("全宗id不能为空",qzId);
        LambdaQueryWrapper<ArcUse> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ArcUse::getQzId, Long.parseLong(qzId.toString())).eq(ArcUse::getIsRemove, ArchiveEnumInteger.IS_FALSE.getCode());
        Long useStoreCount = this.arcUseService.count(lambdaQueryWrapper);

        QueryWrapper<ArcUseRecord> recordQueryWrapper = new QueryWrapper<>();
        recordQueryWrapper.lambda().eq(ArcUseRecord::getQzId,Long.parseLong(qzId.toString()));
        recordQueryWrapper.lambda().groupBy(ArcUseRecord::getVerifyType);
        recordQueryWrapper.select("verifyType","count(*) as count");
        List<Map<String, Object>> list = this.listMaps(recordQueryWrapper);
        Map<String,Long> result = new HashMap<String,Long>();
        result.put("useCount",FlymeUtils.isEmpty(useStoreCount)?0L:useStoreCount);//待借库数量
        result.put("preVerifyCount",0L);//待审核数量
        result.put("preBackCount",0L);//待归还数量
        result.put("overTimeCount",0L);//逾期催还数量
        //TODO 更新利用人数量 黑名单数量
        Integer useUserCount = baseAdminUserService.countByCompanyIdAndStatus(Long.parseLong(qzId.toString()),1);
        Integer useUserBlackCount = baseAdminUserService.countByCompanyIdAndStatus(Long.parseLong(qzId.toString()),0);
        result.put("userCount",FlymeUtils.isEmpty(useUserCount)?0L:Long.parseLong(useUserCount.toString()));//利用人数量
        result.put("blackUserCount",FlymeUtils.isEmpty(useUserBlackCount)?0L:Long.parseLong(useUserBlackCount.toString()));//黑名单数量
        list.forEach(item->{
            Object verifyType = item.get("verifyType");
            Object count = item.get("count");
            if(FlymeUtils.isNotEmpty(verifyType)){
                switch (verifyType.toString()){
                    case "1":
                        result.put("preVerifyCount",Long.parseLong(count.toString()));
                        break;
                    case "3":
                        result.put("preBackCount",Long.parseLong(count.toString()));
                        break;
                    case "5":
                        result.put("overTimeCount",Long.parseLong(count.toString()));
                        break;
                }
            }
        });

        return ResultBody.ok(result);
    }
}
